/*
 * Copyright (c) 2011 Ayan Dave http://www.linkedin.com/in/daveayan
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
 * associated documentation files (the "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
 * following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial 
 * portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package testrj.domain;

import java.util.ArrayList;
import java.util.List;

import testrj.runner.asserter.AsJsonWithoutDateAsserter;
import testrj.runner.asserter.Asserter;

public class TestCase {
	private String id = "1";
	private transient DomainObject currentObject = new DomainObject();
	private transient List<DomainObject> inputParams = new ArrayList<DomainObject>();
	private transient DomainObject returnValue = DomainObject.voidValue();
	private String givenTheStateOfThisObjectIs;
	private List<String> whenMethodIsCalledWithInputParams = new ArrayList<String>();
	private String thenMethodReturns;
	private List<String> thenMethodUpdatesInputParams = new ArrayList<String>();
	private String thenMethodUpdatesUpdatesGlobalParams = "no change";
	private Boolean runAutoTest = true;
	private Asserter asserter = new AsJsonWithoutDateAsserter();

	public void prepareForRun(TestCase ref) {
		this.givenTheStateOfThisObjectIs = ref.getGivenTheStateOfThisObjectIs();
		this.currentObject = DomainObject.asDomainObject(TestrjConfig.persister.getSingleDataSet(ref.getGivenTheStateOfThisObjectIs(), false));
		this.returnValue = DomainObject.asDomainObject(TestrjConfig.persister.getSingleDataSet(ref.getThenMethodReturns(), false));
		for (String inputParamRef : ref.getWhenMethodIsCalledWithInputParams()) {
			this.inputParams.add(DomainObject.asDomainObject(TestrjConfig.persister.getSingleDataSet(inputParamRef, false)));
		}
	}

	public TestCase(Object[] inputParams) {
		this.inputParams = DomainObject.listFromArrayOfParameters(inputParams);
	}

	public boolean persistGlobalParams() {
		this.givenTheStateOfThisObjectIs = TestrjConfig.persister.persistData(currentObject);
		if (currentObject.isParameterUpdated()) {
			thenMethodUpdatesUpdatesGlobalParams = TestrjConfig.persister.persistData(currentObject.reserialize());
			return true;
		}
		return false;
	}

	public boolean persistInputParams() {
		boolean updatesInputParameters = false;
		for (DomainObject domainObject : inputParams) {
			whenMethodIsCalledWithInputParams.add(TestrjConfig.persister.persistData(domainObject));
			if (domainObject.isParameterUpdated()) {
				thenMethodUpdatesInputParams.add(TestrjConfig.persister.persistData(domainObject.reserialize()));
				updatesInputParameters = true;
			} else {
				thenMethodUpdatesInputParams.add("no change");
			}
		}
		return updatesInputParameters;
	}

	public void persistReturnValue() {
		this.thenMethodReturns = TestrjConfig.persister.persistData(returnValue);
	}

	public void setInputParams(List<DomainObject> inputParams) {
		this.inputParams = inputParams;
	}

	public List<DomainObject> getInputParams() {
		return inputParams;
	}

	public void setReturnValue(DomainObject returnValue) {
		this.returnValue = returnValue;
	}

	public String getReturnValueReferenceName() {
		return thenMethodReturns;
	}

	public void setReturnValueReferenceName(String returnValueReferenceName) {
		this.thenMethodReturns = returnValueReferenceName;
	}

	public List<String> getInputParamReferenceNames() {
		return whenMethodIsCalledWithInputParams;
	}

	public void setInputParamReferenceNames(List<String> inputParamReferenceNames) {
		this.whenMethodIsCalledWithInputParams = inputParamReferenceNames;
	}

	public Boolean getRunAutoTest() {
		return runAutoTest;
	}

	public void setRunAutoTest(Boolean runAutoTest) {
		this.runAutoTest = runAutoTest;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public DomainObject getCurrentObject() {
		return currentObject;
	}

	public void setCurrentObject(DomainObject currentObject) {
		this.currentObject = currentObject;
	}

	public String getGivenTheStateOfThisObjectIs() {
		return givenTheStateOfThisObjectIs;
	}

	public void setGivenTheStateOfThisObjectIs(String givenTheStateOfThisObjectIs) {
		this.givenTheStateOfThisObjectIs = givenTheStateOfThisObjectIs;
	}

	public List<String> getWhenMethodIsCalledWithInputParams() {
		return whenMethodIsCalledWithInputParams;
	}

	public void setWhenMethodIsCalledWithInputParams(List<String> whenMethodIsCalledWithInputParams) {
		this.whenMethodIsCalledWithInputParams = whenMethodIsCalledWithInputParams;
	}

	public String getThenMethodReturns() {
		return thenMethodReturns;
	}

	public void setThenMethodReturns(String thenMethodReturns) {
		this.thenMethodReturns = thenMethodReturns;
	}

	public List<String> getThenMethodUpdatesInputParams() {
		return thenMethodUpdatesInputParams;
	}

	public void setThenMethodUpdatesInputParams(List<String> thenMethodUpdatesInputParams) {
		this.thenMethodUpdatesInputParams = thenMethodUpdatesInputParams;
	}

	public TestCase() {
	}

	public String getThenMethodUpdatesUpdatesGlobalParams() {
		return thenMethodUpdatesUpdatesGlobalParams;
	}

	public void setThenMethodUpdatesUpdatesGlobalParams(String thenMethodUpdatesUpdatesGlobalParams) {
		this.thenMethodUpdatesUpdatesGlobalParams = thenMethodUpdatesUpdatesGlobalParams;
	}

	public DomainObject getReturnValue() {
		return returnValue;
	}

	public void setAsserter(Asserter asserter) {
		this.asserter = asserter;
	}
	
	public Asserter getAsserter() {
		return asserter;
	}
}